package de.hska.master.algo;

import java.util.Iterator;
import java.util.Stack;

import javax.swing.JFrame;

import de.hska.master.algo.gui.Viewer;
import de.hska.master.model.Model;
import de.hska.master.model.Point;
import de.hska.master.model.RandomModel;
import de.hska.master.support.Geometry;

public class Controller {

	public static final int VIEWER_WIDTH = 1000;
	public static final int VIEWER_HEIGHT = 800;
	private Viewer viewer = null;

	/**
	 * Sets all for javax.swing needed properties to setup the GUI
	 * 
	 * @param model
	 *            the drawn model
	 */
	public void startViewer(Model model) {
		viewer = new Viewer(model);
		viewer.setVisible(true);
		viewer.setSize(VIEWER_WIDTH, VIEWER_HEIGHT);
		viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		viewer.setLocationRelativeTo(null);
	}

	/**
	 * starts demo by generating a randommodel and starting the grahamalgorithm
	 * on it.
	 * 
	 * @throws InterruptedException
	 */
	public void startDemo() throws InterruptedException {
		// with random points
		Model model = new RandomModel(VIEWER_HEIGHT, VIEWER_WIDTH);
		// Model model = new PointsInACircleModel(100, 300, new Point(500,
		// 500));

		startViewer(model);

		// viewer.addPoints(points);

		// Graham Scan
		GrahamAlgorithm algo = new GrahamAlgorithm(model);
		Stack<Point> result = algo.runAlgorithm();
		Iterator<Point> it = result.iterator();
		while (it.hasNext()) {
			Point p = it.next();
			model.addPointOnConvexHull(p);
		}
		viewer.repaint();

		// Merger Hull
		// MergeHullAlgorithm mergeHull = new MergeHullAlgorithm(model);
		// List<Point> result = mergeHull.runAlgorithm();
		// for (Point point : result) {
		// model.addPointOnConvexHull(point);
		// }
		// viewer.repaint();

	}

	/**
	 * starts performance test by creating a timemeasurement, executing it and
	 * printing the duration.
	 * 
	 * @throws InterruptedException
	 */
	public void startPerformanceTest() throws InterruptedException {
		int numberOfPoints = 900;

		Model model = new Model();
		fillModel(model);
		// startViewer(model);

		// measure the time if all points are in a circle
		TimeMeasurement timeMeasurement = new TimeMeasurement(model);
		double time = 0;
		// if the number of points increases the radius must be big enough
		// otherwise the same points occur multiple times
		// and the algorithm will fail
		timeMeasurement.execAndMeasureAlgorithmGrahamScan();
		time = timeMeasurement.getDuration();

		System.out.println("Time needed for " + numberOfPoints
				+ " points (in a circle): " + time + " milliseconds.");

		// measure the time with random points
		model = new RandomModel(VIEWER_HEIGHT, VIEWER_WIDTH);

		timeMeasurement = new TimeMeasurement(model);
		timeMeasurement.execAndMeasureAlgorithmGrahamScan();
		time = timeMeasurement.getDuration();

		System.out.println("Time needed for " + numberOfPoints
				+ " points (random): " + time + " milliseconds.");
	}

	private void fillModel(Model model) {
		Geometry geometry = new Geometry();
		Point[] points = geometry.getPointsInACircle(900, 1000, new Point(200,
				200));

		for (Point point : points) {
			model.addPoint(point);
		}
	}
}
